/***************************************************
* 文件名：pthread_server.c
* 文件描述：创建子线程来接收客户端的数据
***************************************************/
// #include <sys/types.h>
// #include <sys/socket.h>
// #include <stdio.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
// #include <unistd.h>
// #include <stdlib.h>
// #include <pthread.h>
// #include <string.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>


#define PORT            8080
#define LISTEN_QUEUE    10

void *rec_data(void *fd);

struct pthread_data{
    struct sockaddr_in client_addr;
    int sock_fd;
};

int main(int argc,char *argv[])
{
    int server_sockfd;
    int client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;

    struct pthread_data pdata;  // added by XYH
    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字

    server_address.sin_family = AF_INET;
    // server_address.sin_addr.s_addr =  htonl(INADDR_ANY);
    server_address.sin_addr.s_addr =  INADDR_ANY;
    server_address.sin_port = htons(PORT);

    server_len = sizeof(server_address);

    if( bind(server_sockfd, (struct sockaddr *)&server_address, server_len) == -1 ){//绑定套接字
        fprintf(stderr, "bind function failed\n" );
        exit(-1);
    }

    // templen = sizeof(struct sockaddr);

    if( listen(server_sockfd, LISTEN_QUEUE) == -1 ){
        fprintf(stderr, "listen function failed!\n");
        exit(-1);
    }

    fprintf(stdout, "listening on %d\n", PORT);
    printf("server waiting for connect\n");

    pthread_t thread;//创建不同的子线程以区别不同的客户端
    // client_sockfd = (int *)malloc(sizeof(int));
    client_len = sizeof(client_address);
    while(1) {

        client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, (socklen_t *)&client_len);
        // *client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, &client_len);
        
        if(-1 == client_sockfd) {
            perror("accept\n");
            continue;
        }

        // if(pthread_create(&thread, NULL, rec_data, (void*)client_sockfd)!=0)//创建子线程
        // {
        //     perror("pthread_create\n");
        //     break;
        // }

        pdata.client_addr = client_address;
        pdata.sock_fd = client_sockfd;
        if(pthread_create(&thread, NULL, rec_data, (void*)&pdata)!=0)//创建子线程
        {
            perror("pthread_create\n");
            break;
        }
    }
    // shutdown(client_sockfd,2);
    // shutdown(server_sockfd,2);
    close(client_sockfd);
    close(server_sockfd);

    return 0;
}
/*****************************************
* 函数名称：rec_data
* 功能描述：接受客户端的数据
* 参数列表：fd——连接套接字
* 返回结果：void
*****************************************/
void *rec_data(void *fd)
{
    // int client_sockfd;
    // int byte;
    // char char_recv[1024];//存放数据
    
    // // client_sockfd=*((int*)fd);

    // // modified by XYH
    // struct pthread_data *pdata = (struct pthread_data*)fd;
    // client_sockfd = pdata->sock_fd;


    // // for(;;)
    // while(1)
    // {
    //     // if((byte=recv(client_sockfd,char_recv,1024,0))==-1)
    //     if((byte=recv(client_sockfd,char_recv,sizeof(char_recv),0))==-1)
    //     {
    //         perror("recv");
    //         exit(EXIT_FAILURE);
    //     }
    //     if(strcmp(char_recv, "exit")==0)//接受到exit时，跳出循环
    //         break;
    //     printf("receive from client is %s\n",char_recv);//打印收到的数据
    // }
    // // free(fd);   // 这里free的话会导致服务端出现异常！！！
    // // close(client_sockfd);
    // pthread_exit(NULL);

    struct pthread_data *pdata = (struct pthread_data*)fd;
    int new_fd = pdata->sock_fd;
    char recvbuf[1024];
    char sendbuf[1024] = "recv successfully.\n";
    while(1){
        recv(new_fd, recvbuf, sizeof(recvbuf), 0);
        // fputs(recvbuf,stdout);
        printf("*** %s\n",recvbuf);
        // strcpy(sendbuf, recvbuf);
        if(strcmp(recvbuf,"exit\n") == 0){
            send(new_fd, "connection close.\n", sizeof("connection close.\n"), 0);
            break;
        }
        send(new_fd, sendbuf, sizeof(sendbuf), 0);
        memset(recvbuf,0,sizeof(recvbuf));
    }
    //close(new_fd);评论中指出多了一次close，所以这里不close了，留待main函数中统一close
    pthread_exit(0);

}